import './style.scss'
import type {
  LoadingBarOptions,
  LoadingBarReturn,
} from './type'

const defaultOptions: Partial<LoadingBarOptions> = {
  size: 2,
  step: 0.1,
}
/** 全局进度条 */
export function useLoadingBar(
  target: string | HTMLElement = 'html',
  options?: Partial<LoadingBarOptions>,
): LoadingBarReturn {
  if (typeof target === 'string') {
    target = document.querySelector(target) as HTMLElement
  }
  let container: HTMLElement
  let bar: HTMLElement
  let globalOption: Partial<LoadingBarOptions>
  let globalId: number
  let threshold = 96
  let step = 0.1

  const init = () => {
    globalOption = { ...defaultOptions, ...options }
    container = document.createElement('div')
    container.classList.add('b-loading-container')
    container.style.setProperty(
      '--b-loading-progress',
      '0%',
    )
    bar = document.createElement('div')
    bar.classList.add('b-loading-bar')
    container.appendChild(bar);
    (target as HTMLElement).appendChild(container)
  }

  const start = (opts?: Partial<LoadingBarOptions>) => {
    const newOptions = { ...globalOption, ...opts }
    const size
      = typeof newOptions.size === 'number'
        ? `${newOptions.size}px`
        : newOptions.size
    container.style.setProperty('--b-loading-size', size!)
    container.style.setProperty(
      '--b-loading-progress',
      '0%',
    )
    container.classList.remove('finish')
    container.classList.remove('error')
    clear()

    step = newOptions.step!
    threshold = 96
    run()
  }

  const finish = async () => {
    step = 10
    threshold = 100
    run()
  }
  const error = () => {
    container.classList.add('error')
    finish()
  }
  const run = () => {
    globalId = requestAnimationFrame(() => {
      const progress = getProgress()
      if (progress >= threshold) {
        clear()
        if (threshold >= 100) {
          container.classList.add('finish')
        }
        return
      }
      const newProgress = (progress + step).toFixed(4)
      container.style.setProperty(
        '--b-loading-progress',
        `${newProgress}%`,
      )
      run()
    })
  }
  const clear = () => {
    cancelAnimationFrame(globalId)
  }
  const getProgress = () => {
    const progress = container.style.getPropertyValue(
      '--b-loading-progress',
    )
    return +progress.replace('%', '')
  }

  init()
  return {
    error,
    start,
    finish,
  }
}
